package com.example.repeatsubmit.policy.conretepolicy;

import com.example.repeatsubmit.policy.RepeatPolicy;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.time.Duration;
import java.time.LocalDateTime;

import java.time.temporal.ChronoUnit;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author caoqianhuan
 * @date 2022/8/22
 * @Description:
 */
@Component
public class LocalCachTimeOutRefuse extends RepeatPolicy {
    private SubmitCache submitCache;

    private boolean flag = true;
    public LocalCachTimeOutRefuse() {
        submitCache = new SubmitCache();
    }
    @Override
    public boolean isRepeatSubmit(HttpServletRequest servletRequest)  {
        if (flag) {
            submitCache.init(interval);
            flag = false;
        }
        String preSubmit = getLastRequest(servletRequest);
        if (submitCache.isInPool(preSubmit)) {
            return true;
        }
        submitCache.setSubmit(preSubmit, LocalDateTime.now());
        return false;
    }

    class SubmitCache {

        private ConcurrentHashMap<String, LocalDateTime> submitPool = new ConcurrentHashMap();

        //实例代码块 与对象初始化一起加载，在构造器之前执行
        protected SubmitCache () {

        }

        private void init(long interval) {
            new Thread(() -> {
                while (true) {
                    try {
                        Thread.sleep(interval >> 1);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    LocalDateTime now = LocalDateTime.now();

                    submitPool.forEach( (key, preTime) -> {
                        if (Duration.between(preTime, now).toMillis() > interval)  {
                            submitPool.remove(key);
                        }
                    });
                }
            }, "cacheGC").start();
        }

        protected void setSubmit(String key, LocalDateTime time) {
            submitPool.put(key, time);
        }

        protected boolean isInPool(String key) {
            return submitPool.containsKey(key);
        }


    }
}

